package com.example.appointment.service.impl;

import com.example.appointment.dto.DoctorDTO;
import com.example.appointment.entity.Department;
import com.example.appointment.entity.Doctor;
import com.example.appointment.repository.DepartmentRepository;
import com.example.appointment.repository.DoctorRepository;
import com.example.appointment.service.DoctorService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class DoctorServiceImpl implements DoctorService {

    private final DoctorRepository doctorRepository;
    private final DepartmentRepository departmentRepository;

    @Override
    @Transactional
    public DoctorDTO create(DoctorDTO doctorDTO) {
        // 检查科室是否存在
        Department department = departmentRepository.findById(doctorDTO.getDepartmentId())
                .orElseThrow(() -> new RuntimeException("科室不存在"));

        // 检查医生姓名在同一科室是否已存在
        if (doctorRepository.existsByNameAndDepartmentId(doctorDTO.getName(), doctorDTO.getDepartmentId())) {
            throw new RuntimeException("该科室已存在同名医生");
        }

        // 确保userId字段有值
        if (doctorDTO.getUserId() == null) {
            throw new RuntimeException("用户ID不能为空");
        }

        Doctor doctor = new Doctor();
        doctor.setUserId(doctorDTO.getUserId());  // 显式设置userId
        updateDoctorFromDTO(doctor, doctorDTO, department);
        
        doctor = doctorRepository.save(doctor);
        return convertToDTO(doctor);
    }

    @Override
    @Transactional
    public DoctorDTO update(Long id, DoctorDTO doctorDTO) {
        Doctor doctor = doctorRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("医生不存在"));

        Department department = departmentRepository.findById(doctorDTO.getDepartmentId())
                .orElseThrow(() -> new RuntimeException("科室不存在"));

        // 如果修改了姓名，检查新名称在同一科室是否已存在
        if (!doctor.getName().equals(doctorDTO.getName()) &&
                doctorRepository.existsByNameAndDepartmentId(doctorDTO.getName(), doctorDTO.getDepartmentId())) {
            throw new RuntimeException("该科室已存在同名医生");
        }

        updateDoctorFromDTO(doctor, doctorDTO, department);
        
        doctor = doctorRepository.save(doctor);
        return convertToDTO(doctor);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        if (!doctorRepository.existsById(id)) {
            throw new RuntimeException("医生不存在");
        }
        doctorRepository.deleteById(id);
    }

    @Override
    public DoctorDTO getById(Long id) {
        Doctor doctor = doctorRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("医生不存在"));
        return convertToDTO(doctor);
    }

    @Override
    public Page<DoctorDTO> search(String name, Long departmentId, Boolean status, Pageable pageable) {
        Page<Doctor> doctors;
        
        if (StringUtils.hasText(name) && departmentId != null && status != null) {
            doctors = doctorRepository.findByNameContainingAndDepartmentIdAndStatus(name, departmentId, status, pageable);
        } else if (StringUtils.hasText(name) && status != null) {
            doctors = doctorRepository.findByNameContainingAndStatus(name, status, pageable);
        } else if (departmentId != null && status != null) {
            doctors = doctorRepository.findByDepartmentIdAndStatus(departmentId, status, pageable);
        } else {
            doctors = doctorRepository.findAll(pageable);
        }
        
        return doctors.map(this::convertToDTO);
    }

    @Override
    public List<DoctorDTO> getByDepartment(Long departmentId) {
        return doctorRepository.findByDepartmentId(departmentId)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public DoctorDTO getDoctorByUserId(Long userId) {
        log.info("Fetching doctor info for userId: {}", userId);
        Doctor doctor = doctorRepository.findByUserId(userId)
                .orElseThrow(() -> {
                    log.error("Doctor not found for userId: {}", userId);
                    return new RuntimeException("医生信息不存在");
                });
        log.info("Found doctor: {}", doctor);
        DoctorDTO dto = convertToDTO(doctor);
        log.info("Converted to DTO: {}", dto);
        return dto;
    }

    private void updateDoctorFromDTO(Doctor doctor, DoctorDTO dto, Department department) {
        doctor.setName(dto.getName());
        doctor.setTitle(dto.getTitle());
        doctor.setSpecialty(dto.getSpecialty());
        doctor.setIntroduction(dto.getIntroduction());
        doctor.setPhotoUrl(dto.getPhotoUrl());
        doctor.setDepartment(department);
        doctor.setStatus(dto.getStatus());
        
        // 设置userId，确保与User表关联
        if (dto.getUserId() != null) {
            doctor.setUserId(dto.getUserId());
        }
    }

    private DoctorDTO convertToDTO(Doctor doctor) {
        DoctorDTO dto = new DoctorDTO();
        dto.setId(doctor.getId());
        dto.setUserId(doctor.getUserId());
        dto.setName(doctor.getName());
        dto.setTitle(doctor.getTitle());
        dto.setSpecialty(doctor.getSpecialty());
        dto.setIntroduction(doctor.getIntroduction());
        dto.setPhotoUrl(doctor.getPhotoUrl());
        dto.setDepartmentId(doctor.getDepartment().getId());
        dto.setDepartmentName(doctor.getDepartment().getName());
        dto.setStatus(doctor.getStatus());
        return dto;
    }
} 